﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NFinal.Extension;

namespace NFinal
{
    /// <summary>
    /// Action抽像类
    /// </summary>
    public abstract class Action : MagicAction, IAction
    {
        /// <summary>
        /// 请求的根路径，例：http://www.x.com
        /// </summary>
        public abstract string RequestRoot
        {
            get;
        }
        
        /// <summary>
        /// 
        /// </summary>
        public Action()
        {
            this._serverType = ServerType.UnKnown;
        }
        /// <summary>
        /// 基于文本输出对象的初始化函数
        /// </summary>
        /// <param name="tw">文本输出对象</param>
        public Action(System.IO.TextWriter tw)
        {
            this._serverType = ServerType.IsStatic;
            this._tw = tw;
        }
        /// <summary>
        /// 静态html页输出初始化函数
        /// </summary>
        /// <param name="fileName"></param>
        public Action(string fileName)
        {
            this._serverType = ServerType.IsStatic;
            System.IO.StreamWriter sw = new System.IO.StreamWriter(MapPath(fileName), false, Constant.encoding);
            this._tw = sw;
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="action"></param>
        public Action(Action action)
        {
            action._serverType = this._serverType;
            action._methodType = this._methodType;
            action._subdomain = this._subdomain;
            action._url = this._url;
            action._get = this._get;
            action._files = this._files;
            action._app = this._app;
        }
        /// <summary>
        /// 是否是手机端
        /// </summary>
        /// <param name="userAgent"></param>
        /// <returns></returns>
        private static bool IsMobile(string userAgent)
        {
            string agent = userAgent;
            bool isMobile = false;
            string[] keywords = { "Android", "iPhone", "iPod", "iPad", "Windows Phone", "MQQBrowser" };

            //排除 Windows 桌面系统  
            if (!agent.Contains("Windows NT") || (agent.Contains("Windows NT") && agent.Contains("compatible; MSIE 9.0;")))
            {
                //排除 苹果桌面系统  
                if (!agent.Contains("Windows NT") && !agent.Contains("Macintosh"))
                {
                    foreach (string item in keywords)
                    {
                        if (agent.Contains(item))
                        {
                            isMobile = true;
                            break;
                        }
                    }
                }
            }
            return isMobile;
        }
        /// <summary>
        /// 请求返回的页面类型
        /// </summary>
        public string ContentType
        {
            set
            {
                SetResponseHeader("Content-Type", value);
            }
            get
            {
                return GetRequestHeader("Content-Type");
            }
        }
        /// <summary>
        /// 请求内容
        /// </summary>
        public abstract System.IO.Stream InputStream { get; }
        /// <summary>
        /// 是否是移动设备
        /// </summary>
        public bool _isMobile = false;
        /// <summary>
        /// 服务器类型
        /// </summary>
        public ServerType _serverType = ServerType.UnKnown;
        /// <summary>
        /// 从get和post中获取的请求参数
        /// </summary>
        public NameValueCollection _get;
        /// <summary>
        /// 从前端传过来的文件
        /// </summary>
        public IDictionary<string, HttpFile> _files = null;
        /// <summary>
        /// 页面输出对象，类似于response.output对象。
        /// </summary>
        public TextWriter _tw = null;
        /// <summary>
        /// 页面的二级域名
        /// </summary>
        public string _subdomain;//二级域名
        /// <summary>
        /// 页面的模块名
        /// </summary>
        public string _app;
        /// <summary>
        /// 请求的url
        /// </summary>
        public string _url;
        /// <summary>
        /// 请求的方法，get,post
        /// </summary>
        public NFinal.MethodType _methodType = NFinal.MethodType.NONE;
        /// <summary>
        /// 渲染html模板
        /// </summary>
        /// <param name="tplPath">模板相对路径,一般相对于App/Views/Default目录</param>
        public sealed override void View(string tplPath) { }
        /// <summary>
        /// 渲染html模板
        /// </summary>
        /// <param name="name">模板样式</param>
        /// <param name="tplPath">模板相对路径,一般相对于App/Views/Default目录</param>
        public sealed override void View(string name, string tplPath) { }
        /// <summary>
        /// 请求是否来自移动端
        /// </summary>
        public bool isMobile
        {
            get
            {
                string userAgent = GetRequestHeader("User-Agent");
                _isMobile = IsMobile(userAgent);
                return _isMobile;
            }
        }
        /// <summary>
        /// 返回服务器路径
        /// </summary>
        /// <param name="path">相对路径</param>
        /// <returns></returns>
        public static string MapPath(string path)
        {
            return NFinal.Utility.MapPath(path);
        }
        /// <summary>
        /// 模板渲染前函数，用于子类重写
        /// </summary>
        public void AjaxReturn()
        {

        }
        /// <summary>
        /// 模板渲染后函数，用于子类重写
        /// </summary>
        public abstract void Before();
        /// <summary>
        /// 模板渲染后函数，用于子类重写
        /// </summary>
        public abstract void After();
        /// <summary>
        /// 停止输出
        /// </summary>
        public abstract void Close();
        /// <summary>
        /// 输出一行
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        public void WriteLine<T>(T obj)
        {
            Write(obj.ToString());
            Write("<br/>");
        }
        /// <summary>
        /// 输出字符串
        /// </summary>
        /// <param name="obj"></param>
        public void Write(string obj)
        {
            if (obj != null)
            {
                Write(Constant.encoding.GetBytes(obj));
            }
        }
        /// <summary>
        /// 输出字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        public void Write<T>(T obj)
        {
            Write(obj.ToString());
        }
        /// <summary>
        /// 输出字节流
        /// </summary>
        /// <param name="buffer"></param>
        public void Write(byte[] buffer)
        {
            if (buffer != null)
            {
                Write(buffer, 0, buffer.Length);
            }
        }
        /// <summary>
        /// 输出字节流
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="start"></param>
        /// <param name="cout"></param>
        public abstract void Write(byte[] buffer, int start, int cout);
        /// <summary>
        /// 返回true或false
        /// </summary>
        /// <param name="obj">bool变量</param>
        public void AjaxReturn(bool obj)
        {
            this.ContentType = "application/json;charset=utf-8";
            this.Write(obj ? "true" : "false");
        }
        /// <summary>
        /// 返回表数据对象对应的json字符串{code:[code状态码],msg:[msg消息],result:[表数据对应的json对象]}
        /// </summary>
        /// <typeparam name="T">表数据，NFinal.List对象</typeparam>
        /// <param name="obj">表数据对应的json对象</param>
        public void AjaxReturn<T>(List<T> obj) where T : IModel
        {
            this.AjaxReturn(obj.ToJson(), obj==null ? 1 : 0, "");
        }
        /// <summary>
        /// 返回json字符串{code:[code状态码],msg:[msg消息],result:[json字符串]}
        /// </summary>
        /// <param name="json">json字符串</param>
        /// <param name="code">状态码</param>
        /// <param name="msg">消息</param>
        public void AjaxReturn(string json, int code, string msg)
        {
            this.ContentType = "application/json;charset=utf-8";
            this.Write(string.Format("{{\"code\":{0},\"msg\":\"{1}\",\"result\":{2}}}", code, msg, json));
        }
        /// <summary>
        /// 返回数据库实体类对应的json对象{code:[code状态码],msg:[msg消息],result:[json对象]}
        /// </summary>
        /// <param name="str">数据库实体类</param>
        /// <param name="code">状态码</param>
        /// <param name="msg">消息</param>
        public void AjaxReturn(IModel model, int code, string msg)
        {
            if (model == null)
            {
                AjaxReturn("null", code, msg);
            }
            else
            {
                AjaxReturn(model.ToJson(), code, msg);
            }
        }
        /// <summary>
        /// 返回数据库实体类对应的json对象{code:1,msg:"",result:[json对象]}
        /// </summary>
        /// <param name="obj">数据库实体类</param>
        public void AjaxReturn(dynamic obj)
        {
            AjaxReturn(obj.ToJson());
        }
        /// <summary>
        /// 返回数据库实体类对应的json对象{code:1,msg:"",result:[json对象]}
        /// </summary>
        /// <param name="str">数据库实体类</param>
        public void AjaxReturn(IModel model)
        {
            if (model == null)
            {
                AjaxReturn("null");
            }
            else
            {
                AjaxReturn(model?.ToJson());
            }
        }
        /// <summary>
        /// 设置响应头
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public abstract void SetResponseHeader(string key, string value);
        /// <summary>
        /// 设置响应头
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public abstract void SetResponseHeader(string key, string[] value);
        /// <summary>
        /// 读取请求头
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public abstract string GetRequestHeader(string key);
        /// <summary>
        /// 设置状态码
        /// </summary>
        /// <param name="statusCode"></param>
        public abstract void SetResponseStatusCode(int statusCode);
        /// <summary>
        /// 页面重定向
        /// </summary>
        /// <param name="url"></param>
        public void Redirect(string url)
        {
            this.SetResponseStatusCode(302);
            this.ContentType = "text/html ;charset=utf-8";
            this.SetResponseHeader("Location", url);
        }
        /// <summary>
        /// 返回json{code:1,msg:"",result:[json字符串]}
        /// </summary>
        /// <param name="json">json字符串</param>
        public void AjaxReturn(string json)
        {
            this.ContentType = "text/json ;charset=utf-8";
            this.Write(json);
        }
    }
}
